#include "gd32l23x.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesADC.h"
#include "DevicesPID.h"
#include "DevicesPWM.h"
#include "DevicesTimer.h"
#include "DriverDCDC.h"


DCDCPortType g_typeDCDCPort;

/* 稳压、稳流PID调节数据 */
PIDType st_typePidVoltage;
PIDType st_typePidCurrent;
PIDType st_typePidCurrentB;


void vDCDCxInit(void)
{
    cTimer1PWMOutInit();
    cTimer2PWMOutInit();

    vPIDDeInit(&st_typePidVoltage,  PID_VOLTAGE_P, PID_VOLTAGE_I, PID_VOLTAGE_D, PID_VOLTAGE_EMAX, PID_VOLTAGE_IMAX, PID_VOLTAGE_IMIN, PID_VOLTAGE_OMAX, PID_VOLTAGE_OMIN);
    vPIDDeInit(&st_typePidCurrent,  PID_CURRENT_P, PID_CURRENT_I, PID_CURRENT_D, PID_CURRENT_EMAX, PID_CURRENT_IMAX, PID_CURRENT_IMIN, PID_CURRENT_OMAX, PID_CURRENT_OMIN);
    vPIDDeInit(&st_typePidCurrentB, PID_CURRENT_P, PID_CURRENT_I, PID_CURRENT_D, PID_CURRENT_EMAX, PID_CURRENT_IMAX, PID_CURRENT_IMIN, PID_CURRENT_OMAX, PID_CURRENT_OMIN);

    cDCDCxVoltageSet(24000);

    cDCDCxOpen();
}

int8_t cDCDCxOpen(void)
{
    g_typeDCDCPort.switchs = ENABLE;

    nvic_irq_enable(TIMER8_IRQn, 0);

    return 0;
}

int8_t cDCDCxClose(void)
{
    g_typeDCDCPort.switchs = DISABLE;

    nvic_irq_disable(TIMER8_IRQn);

    vTimerxChannel0lPlusSet(DCDC_BUCK_TIMER, 0);
    vTimerxChannel23PlusSet(DCDC_BOOST_TIMER, 0);
    vTimerxChannel0lPlusSet(DCDC_BUCK_B_TIMER, 0);
    vTimerxChannel23PlusSet(DCDC_BOOST_B_TIMER, 0);

    return 0;
}

int8_t cDCDCxVoltageSet(int32_t iValue)
{
    g_typeDCDCPort.voltageOutSet = iValue;

    return 0;
}

int8_t cDCDCxControl(void)
{
    int32_t iPulse = 0, iPulseB = 0, iBuckPulse, iBoostPulse, iVoltage;

    /* 获取电压值 */
    iVoltage = iADCGetDMAValue(ADC_DMA_SCAN_DCDC_OUT_VOLTAGE);
    g_typeDCDCPort.voltageOut = iVoltage * 10;

    /* 获取电流值 */
    iVoltage = iADCGetDMAValue(ADC_DMA_SCAN_DCDC_INDUCTIVE_CURRENT);
    g_typeDCDCPort.currentInductive = iVoltage * 10;

    /* 获取电流值 */
    iVoltage = iADCGetDMAValue(ADC_DMA_SCAN_DCDC_B_INDUCTIVE_CURRENT);
    g_typeDCDCPort.currentInductiveB = iVoltage * 10;


    /* 关闭时，要清除积分，防止开启瞬间过冲 */
    if(g_typeDCDCPort.switchs == 0)
    {
        st_typePidVoltage.integral = 0;
        st_typePidCurrent.integral = 0;
        st_typePidCurrentB.integral = 0;

        /* 缓启动重新开始 */
        g_typeDCDCPort.voltageOutSlowStart = 0;
    }
    else
    {
        /* 缓启系数 */
        #define DCDC_VOLTAGE_SLOW   1

        /* 每次主动开启电源时，需要缓启动 */
        g_typeDCDCPort.voltageOutSlowStart = ((g_typeDCDCPort.voltageOutSet * DCDC_VOLTAGE_SLOW) + (g_typeDCDCPort.voltageOutSlowStart * (1000 - DCDC_VOLTAGE_SLOW))) / 1000;

        /* 电压环 */
        g_typeDCDCPort.currentInductiveSet = iPIDLocation(&st_typePidVoltage, g_typeDCDCPort.voltageOutSlowStart, g_typeDCDCPort.voltageOut) / 1000;

        /* 电流环 */
        iPulse = iPIDLocation(&st_typePidCurrent, g_typeDCDCPort.currentInductiveSet, g_typeDCDCPort.currentInductive) / 1000;

        /* 电流环 */
        iPulseB = iPIDLocation(&st_typePidCurrent, g_typeDCDCPort.currentInductiveSet, g_typeDCDCPort.currentInductiveB) / 1000;
    }

    /* 前50%:buck、后50%:boost */
    iBuckPulse  = (iPulse > DCDC_PULSE_MAX) ? DCDC_PULSE_MAX : ((iPulse < 0) ? 0 : iPulse);
    iPulse -= DCDC_PULSE_MAX;
    iBoostPulse = (iPulse > DCDC_PULSE_MAX) ? DCDC_PULSE_MAX : ((iPulse < 0) ? 0 : iPulse);

    vTimerxChannel0lPlusSet(DCDC_BUCK_TIMER, iBuckPulse);
    vTimerxChannel23PlusSet(DCDC_BOOST_TIMER, iBoostPulse);

    /* 前50%:buck、后50%:boost */
    iBuckPulse  = (iPulseB > DCDC_PULSE_MAX) ? DCDC_PULSE_MAX : ((iPulseB < 0) ? 0 : iPulseB);
    iPulseB -= DCDC_PULSE_MAX;
    iBoostPulse = (iPulseB > DCDC_PULSE_MAX) ? DCDC_PULSE_MAX : ((iPulseB < 0) ? 0 : iPulseB);

    vTimerxChannel0lPlusSet(DCDC_BUCK_B_TIMER, iBuckPulse);
    vTimerxChannel23PlusSet(DCDC_BOOST_B_TIMER, iBoostPulse);


/* 滤波系数 */
#define DCDC_FILTER     1

    g_typeDCDCPort.currentOut        = g_typeDCDCPort.currentInductive + g_typeDCDCPort.currentInductiveB;

    g_typeDCDCPort.voltageOutFilter  = (g_typeDCDCPort.voltageOut * DCDC_FILTER + g_typeDCDCPort.voltageOutFilter * (1000 - DCDC_FILTER)) / 1000;
    g_typeDCDCPort.currentOutFilter  = (g_typeDCDCPort.currentOut * DCDC_FILTER + g_typeDCDCPort.currentOutFilter * (1000 - DCDC_FILTER)) / 1000;
    g_typeDCDCPort.powerOutFilter    = g_typeDCDCPort.voltageOutFilter * g_typeDCDCPort.currentOutFilter / 1000;

    return 0;
}

DCDCPortType *ptypeDCDCxInfoGet(void)
{
    return &g_typeDCDCPort;
}
